using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

namespace csctp
{
	public class ctp_quote
	{
        private readonly List<Delegate> _listDele = new List<Delegate>();
        Delegate AddDele(Delegate d) { _listDele.Add(d); return d; }

		#region	响应函数 extern
		[[ range .On]]public delegate void Dele[[ .FuncName ]]([[ range $i,$v := .FuncFields ]][[ if gt $i 0 ]], [[ end ]][[ .FieldType|fieldType ]] [[ .FieldName|trimStar ]][[ end ]]);
		/// <summary>
		/// [[ .Comment ]]
		/// </summary>
		public Dele[[ .FuncName ]] On[[ .FuncName ]] = null;
		private void on[[ .FuncName ]]([[ range $i,$v := .FuncFields ]][[ if gt $i 0 ]], [[ end ]][[ .FieldType|fndele ]] [[ .FieldName|trimStar ]][[ end ]])
        {
			if (On[[ .FuncName ]] == null)
            {
				return;
            }[[ range .FuncFields ]][[ if eq (.FieldName|trimStar|leftOne) "p" ]]			
			var p[[ .FieldName|trimStar ]] = new [[ .FieldType ]]();
			if ([[ .FieldName|trimStar ]] != IntPtr.Zero)
			{
				p[[ .FieldName|trimStar ]] = Marshal.PtrToStructure<[[ .FieldType ]]>([[ .FieldName|trimStar ]]);
			}
			[[ end ]][[ end ]][[/*在类型为 struct 的变量名前加p*/]]
			On[[ .FuncName ]]([[ range $i,$v := .FuncFields ]][[ if gt $i 0 ]], [[ end ]][[ if eq (.FieldName|trimStar|leftOne) "p" ]]p[[end]][[ .FieldName|trimStar ]][[ end ]]);
		}
		[[ end ]]
		#endregion

		IntPtr _handle = IntPtr.Zero, _api = IntPtr.Zero, _spi = IntPtr.Zero;
		
		public ctp_quote()
		{
			Directory.CreateDirectory("log");
			_api = qCreateApi();
			_spi = qCreateSpi();
			qRegisterSpi(_api, _spi);

			#region 注册事件,用adddele避免被回收
			[[ range .On ]]qSetOn[[ .FuncName ]](_spi, (dele[[.FuncName]])AddDele(new dele[[.FuncName]]((on[[ .FuncName ]]))));
			[[ end ]]
			#endregion
		}
		[DllImport("ctp_quote.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr qCreateApi();
		[DllImport("ctp_quote.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr qCreateSpi();
		[DllImport("ctp_quote.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr qGetVersion();
		public string GetVersion() => Marshal.PtrToStringAnsi(qGetVersion())??"";
		[[ range .Fn ]]
		[DllImport("ctp_quote.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr q[[ .FuncName ]](IntPtr api[[ range .FuncFields ]], [[ if eq (.FieldName|trimStar) "ppInstrumentID" ]]IntPtr[[ else ]][[ .FieldType|refFieldType ]][[ end ]] [[ .FieldName|trimStar ]][[ end ]]);
		/// <summary>
		/// [[ .Comment ]]
		/// </summary>
		public void [[ .FuncName ]]([[ range $i,$v := .FuncFields ]][[ if gt $i 0 ]], [[ end ]][[ if eq (.FieldName|trimStar) "ppInstrumentID" ]]IntPtr[[ else ]][[ .FieldType|fieldType ]][[ end ]] [[ .FieldName|trimStar ]][[ end ]])
		{
			q[[ .FuncName ]](_api[[ range .FuncFields ]], [[ param .FieldType (.FieldName|trimStar) ]][[ end ]]);
		}
		[[ end ]]

		#region 注册响应函数
		[[ range .On]]
		[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)]
		private delegate void dele[[ .FuncName ]]([[ range $i,$v := .FuncFields ]][[ if gt $i 0 ]], [[ end ]][[ .FieldType|fndele ]] [[ .FieldName|trimStar ]][[ end ]]);
		[DllImport("ctp_quote.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr qSetOn[[ .FuncName ]](IntPtr spi, dele[[ .FuncName ]] func);
		[[ end ]]
		#endregion
	}
}